package com.xy.webadmin.upms.util;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.StrUtil;
import com.xy.common.core.constant.ErrorCodeEnum;
import com.xy.common.core.object.ResponseResult;
import com.xy.common.core.object.TokenData;
import com.xy.common.core.upload.BaseUpDownloader;
import com.xy.common.core.upload.UpDownloaderFactory;
import com.xy.common.core.upload.UploadResponseInfo;
import com.xy.common.core.upload.UploadStoreInfo;
import com.xy.common.core.upload.UploadStoreTypeEnum;
import com.xy.common.core.util.ContextUtil;
import com.xy.common.core.util.MyModelUtil;
import com.xy.common.ext.config.CommonExtProperties;
import com.xy.webadmin.upms.model.MobileMenu;
import com.xy.webadmin.upms.service.MobileMenuService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBinaryStream;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

/**
 * 移动端菜单操作辅助类
 */
@Slf4j
@Component
public class MobileMenuHelper {

    @Autowired
    private MobileMenuService mobileMenuService;

    @Autowired
    private CommonExtProperties properties;

    @Autowired
    private UpDownloaderFactory upDownloaderFactory;

    @Autowired
    private RedissonClient redissonClient;

    private static final String MOBILE_MENU_PREFIX = "MobileMenu";

    /**
     * 文件下载
     *
     * @param fieldName 字段名
     * @param filename 文件名
     * @param asImage 是否作为图片下载
     * @param response 响应对象
     */
    public void download(String fieldName, String filename, Boolean asImage, HttpServletResponse response) {
        try {
            // 验证会话缓存中的文件
            TokenData tokenData = TokenData.takeFromRequest();
            String key = tokenData.getSessionId() + filename;
            RBinaryStream stream = redissonClient.getBinaryStream(key);
            if (!stream.isExists()) {
                ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
                        ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, "无效的会话缓存文件！"));
                return;
            }
            UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(MobileMenu.class, fieldName);
            if (!storeInfo.isSupportUpload()) {
                ResponseResult.output(HttpServletResponse.SC_NOT_IMPLEMENTED,
                        ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD));
                return;
            }
            BaseUpDownloader upDownloader = upDownloaderFactory.get(
                    EnumUtil.getEnumAt(UploadStoreTypeEnum.class, properties.getUploadStoreType()));
            upDownloader.doDownload(properties.getUploadFileBaseDir(),
                    MOBILE_MENU_PREFIX, fieldName, filename, asImage, response);
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            log.error("Failed to download file", e);
        }
    }

    /**
     * 文件上传
     *
     * @param fieldName 字段名
     * @param asImage 是否作为图片上传
     * @param uploadFile 上传文件
     * @return 上传响应信息
     */
    public UploadResponseInfo upload(String fieldName, Boolean asImage, MultipartFile uploadFile) throws IOException {
        UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(MobileMenu.class, fieldName);
        if (!storeInfo.isSupportUpload()) {
            ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
                    ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD));
            return null;
        }

        BaseUpDownloader upDownloader = upDownloaderFactory.get(
                EnumUtil.getEnumAt(UploadStoreTypeEnum.class, properties.getUploadStoreType()));
        UploadResponseInfo responseInfo = upDownloader.doUpload(null,
                properties.getUploadFileBaseDir(), MOBILE_MENU_PREFIX, fieldName, asImage, uploadFile);
        if (BooleanUtil.isTrue(responseInfo.getUploadFailed())) {
            ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
                    ResponseResult.error(ErrorCodeEnum.UPLOAD_FAILED, responseInfo.getErrorMessage()));
            return null;
        }

        // 保存到会话缓存
        TokenData tokenData = TokenData.takeFromRequest();
        String key = tokenData.getSessionId() + responseInfo.getFilename();
        RBinaryStream stream = redissonClient.getBinaryStream(key);
        stream.set(uploadFile.getBytes());

        // 设置下载URI
        String uploadUri = ContextUtil.getHttpRequest().getRequestURI();

        uploadUri = StrUtil.removeSuffix(uploadUri, "/");

        uploadUri = StrUtil.removeSuffix(uploadUri, "/upload");

        responseInfo.setDownloadUri(uploadUri + "/download");

        return responseInfo;
    }

    /**
     * 保存上传文件信息到数据库
     *
     * @param mobileMenu 移动端菜单对象
     * @param fieldName 字段名
     * @param uploadResponseInfo 上传响应信息
     * @throws IOException 如果上传过程中发生IO异常
     */
    public void saveUploadInfo(MobileMenu mobileMenu, String fieldName, UploadResponseInfo uploadResponseInfo) throws IOException {
        if (mobileMenu == null || uploadResponseInfo == null) {
            return;
        }

        UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(MobileMenu.class, fieldName);
        if (!storeInfo.isSupportUpload()) {
            ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
                    ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD));
            return;
        }

        // 验证会话缓存
        TokenData tokenData = TokenData.takeFromRequest();
        String key = tokenData.getSessionId() + uploadResponseInfo.getFilename();
        RBinaryStream stream = redissonClient.getBinaryStream(key);
        if (!stream.isExists()) {
            ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
                    ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, "无效的会话缓存文件！"));
            return;
        }

        BaseUpDownloader upDownloader = upDownloaderFactory.get(
                EnumUtil.getEnumAt(UploadStoreTypeEnum.class, properties.getUploadStoreType()));
        upDownloader.doUpload(null, properties.getUploadFileBaseDir(),
                MOBILE_MENU_PREFIX, fieldName, true, null);
        mobileMenuService.updateById(mobileMenu);

        // 清理会话缓存
        stream.delete();
    }
}
